<?php
/**
 * Created by PhpStorm.
 * User: xiao
 * Date: 2018/8/29
 * Time: 15:05
 */

namespace app\index\controller;


use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Message\AMQPMessage;
use PhpAmqpLib\Wire\AMQPTable;
use think\Controller;

class Message extends Controller
{
    // 这是正常的
    public $queue = 'order_queue';              // 队列
    public $routeKey = 'order_route_queue';     // 队列和交换器的key
    public $exchangeName = 'order_exchange';    // 交换器名称

    // 这里是死信的
    public $deadQueue = 'dead_queue';
    public $deadRouteKey = 'dead_route_queue';
    public $deadExchange = 'dead_exchange';


    public function client()
    {

        $connection = new AMQPStreamConnection('localhost',  5672, 'guest', 'guest');
        $channel = $connection->channel();

        // ########  正常的声明  ########
        // 交换器设置， direct 直连交换器，该交换机将会对绑定键（binding key）和路由键（routing key）进行精确匹配
        $channel->exchange_declare($this->exchangeName,'direct',false, true, false);
        // 队列声明
        $channel->queue_declare($this->queue, false, true, false, false);
        // 队列和交换器绑定
        $channel->queue_bind($this->queue, $this->exchangeName, $this->routeKey);
        // #############################

        $msg = new AMQPMessage('Hello World!');

        $channel->basic_publish($msg, $this->deadExchange, $this->deadRouteKey);

        echo 'send';

        $channel->close();
        $connection->close();
    }

    public function server()
    {
        $connection = new AMQPStreamConnection('localhost',  5672, 'guest', 'guest');
        $channel = $connection->channel();
        // 1. 队列名称  3.持久的消息
        $channel->queue_declare($this->queue, false, true, false, false);

        // 交换器设置， direct 直连交换器，该交换机将会对绑定键（binding key）和路由键（routing key）进行精确匹配
        $channel->exchange_declare($this->exchangeName,'direct',false, true, false);

        // 队列和交换器绑定
        $channel->queue_bind($this->queue, $this->exchangeName, $this->routeKey);

        $callback = function($msg) {
            echo " [x] Received ", $msg->body, "\n";

            // 当no_ack=false时， 需要写下行代码，否则可能出现内存不足情况
            // 告知消息已经处理完成,只有告知消息处理成功这条消息才算被消费
            $msg->delivery_info['channel']->basic_ack($msg->delivery_info['delivery_tag']);
        };

        // 这里设置了no_act,就是不自动提交
        $channel->basic_consume($this->queue, '', false, false, false, false, $callback);

        #监听消息，一有消息，立马就处理
        while(count($channel->callbacks)) {
            $channel->wait();
        }
        $channel->close();
        $connection->close();
    }

}